package main

// 变量遮蔽的问题

import (
	"errors"
	"fmt"
)

var a int = 2020 // 声明包级变量 a

func checkYear() error {
	err := errors.New("wrong year")

	// 控制语句隐式代码块，有同名变量 a 和 err
	// a 和 err 在隐式代码块里遮蔽了包级变量 a 和外层代码块变量 err
	switch a, err := getYear(); a {
	case 2020:
		fmt.Println("it is", a, err)
	case 2021:
		fmt.Println("it is", a)
		err = nil // 复制的是内层代码块的 err，没有改变外层的 err
	}

	// switch 隐式代码块作用域结束后， 读取到的仍然是包级变量 a 的值
	fmt.Println("after call checkYear(), a is", a)

	// switch 隐式代码块作用域结束后， 返回的是 swtich 外层代码块的 err
	return err
}

func checkYearV2() error {
	defaultErr := errors.New("wrong year")

	// 控制语句隐式代码块，有同名变量 a 和 err
	// a 和 err 在隐式代码块里遮蔽了包级变量 a 和外层代码块变量 err
	switch a, err := getYear(); a {
	case 2020:
		fmt.Println("it is", a, err)
		return defaultErr
	case 2021:
		fmt.Println("it is", a)
		return nil
	default:
		return defaultErr
	}
}

// 声明了名为 new 的变量，遮蔽了预定义标识符 new
type new int

func getYear() (new, error) {
	var b = int16(2021)
	return new(b), nil
}

func main() {
	// 由于变量遮蔽， err 不是 nil
	// err := checkYear()
	// if err != nil {
	// 	fmt.Println("check year failed!", err.Error())
	// }

	// 改进版本
	err2 := checkYearV2()
	if err2 != nil {
		fmt.Println("check year failed!", err2.Error())
	}
}
